/* vector_field.h */

#ifndef DODO_VECTOR_FIELD_H
#define DODO_VECTOR_FIELD_H

#include <list>
#include <dodo_plot/kernel/plotfwd.h>
#include <dodo_plot/kernel/basic_elements.h>
#include <dodo_plot/kernel/plotter.h>

namespace dodo_plot
{

/**
 * 以某种符号来绘制矢量场(不限于矢量)
 */
/// 矢量场
template<class Sym_T>
class Vector_Field
{
public:
	/**
	 * 需要表示数据值, 所在x坐标, y坐标的迭代器们.
	 * \param data_proj 将数据转换为符号的函数.
	 * \param xy_proj 将(x, y)转换为Point的函数. 可以为地图投影等仿函数. 
	 */
	template<class Data_Iter, class X_Iter, class Y_Iter, class X_T, class Y_T, class Data_Proj, class XY_Proj_T>
	Vector_Field(Data_Iter data_b, Data_Iter data_e, X_Iter x_b, Y_Iter y_b, 
		const X_T& x_min, const X_T& x_max,
		const Y_T& y_min, const Y_T& y_max,
		const Data_Proj& data_proj, const XY_Proj_T& xy_proj);

public:
	double width() const {return 1.0;}
	double height() const {return 1.0;}
	Position local_pos() const {return local_pos_;}
	void draw(const Plotter& plotter) const;
private:
	std::list<double> x_;
	std::list<double> y_;
	std::list<Sym_T> data_;
	Position local_pos_;
};

// Implement
template<class Sym_T>
template<class Data_Iter, class X_Iter, class Y_Iter, class X_T, class Y_T, class Data_Proj, class XY_Proj_T>
Vector_Field<Sym_T>::Vector_Field(Data_Iter data_b, Data_Iter data_e, X_Iter x_b, Y_Iter y_b, 
	const X_T& x_min, const X_T& x_max,
	const Y_T& y_min, const Y_T& y_max,
	const Data_Proj& data_proj, const XY_Proj_T& xy_proj)
{
	for(; data_b != data_e; ++data_b, ++x_b, ++y_b)
	{
		Point p = xy_proj(*x_b, *y_b);
		x_.push_back(p.x);
		y_.push_back(p.y);
		data_.push_back(data_proj(*data_b));
	}

	Point p_tl = xy_proj(x_min, y_min);
	Point p_br = xy_proj(x_max, y_max);
	local_pos_ = Position(p_tl, p_br);
}

template<class Sym_T>
void Vector_Field<Sym_T>::draw(const Plotter& plotter) const
{
	plotter.save();
	plotter.begin_new_path();
	std::list<double>::const_iterator x_iter = x_.begin();
	std::list<double>::const_iterator y_iter = y_.begin();
	typename std::list<Sym_T>::const_iterator data_iter = data_.begin();
	for( ; data_iter != data_.end(); ++x_iter, ++y_iter, ++data_iter)
	{
		Plotter sym_plotter = plotter.sub_plotter(
			Position(*x_iter, *x_iter, *y_iter, *y_iter),
			data_iter->local_pos()
			);
		data_iter->draw(sym_plotter);
	}
	plotter.restore();
}

}

#endif //DODO_VECTOR_FIELD_H

